package com.bbm.bbmanage.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bbm.bbmanage.entity.AppHttpCodeEnum;
import com.bbm.bbmanage.entity.House;
import com.bbm.bbmanage.entity.Reserve;
import com.bbm.bbmanage.entity.consts.SysConst;
import com.bbm.bbmanage.entity.dto.IdList;
import com.bbm.bbmanage.entity.vo.PageVo;
import com.bbm.bbmanage.entity.vo.ReserveVo;
import com.bbm.bbmanage.entity.vo.ResponseResult;
import com.bbm.bbmanage.mapper.ReserveMapper;
import com.bbm.bbmanage.service.HouseService;
import com.bbm.bbmanage.service.ReserveService;
import com.bbm.bbmanage.util.BeanCopyUtils;
import com.bbm.bbmanage.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 房间预定表(Reserve)表服务实现类
 *
 * @author lionkliu
 * @since 2023-12-13 11:41:44
 */
@Service("reserveService")
public class ReserveServiceImpl extends ServiceImpl<ReserveMapper, Reserve> implements ReserveService {
    @Autowired
    private HouseService houseService;

    @Override
    public ResponseResult selectPage(Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<Reserve> queryWrapper = new LambdaQueryWrapper<>();
        Page<Reserve> page = new Page<>(pageNum, pageSize);
        Page<Reserve> reservePage = page(page, queryWrapper);
        PageVo<Reserve> pageVo = new PageVo<>();
        pageVo.setResult(reservePage.getRecords());
        pageVo.setTotal(reservePage.getTotal());
        pageVo.setPageTotal(pageVo.getPageTotal(pageSize));
        return ResponseResult.okResult(pageVo);
    }

    @Override
    public ResponseResult selectOne(Integer id) {
        return ResponseResult.okResult(getById(id));
    }

    @Transactional
    @Override
    public ResponseResult insertOne(Reserve reserve) {
        LambdaQueryWrapper<House> houseLambdaQueryWrapper = new LambdaQueryWrapper<House>().eq(House::getId, reserve.getHouseId());
        House house = houseService.getOne(houseLambdaQueryWrapper);


        LambdaUpdateWrapper<House> houseLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        houseLambdaUpdateWrapper.eq(House::getId, reserve.getHouseId());
        if (house.getRest() > 0) {
            Integer rest = house.getRest() - 1;
            houseLambdaUpdateWrapper.set(House::getRest, rest);
            houseService.update(null, houseLambdaUpdateWrapper);
        }


        return save(reserve) ? ResponseResult.okResult() : ResponseResult.errorResult(AppHttpCodeEnum.INSERT_ERROR);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult deleteById(Integer id) {
        Reserve reserve = getById(id);
        Long houseId = reserve.getHouseId();
        House house = houseService.getById(houseId);
        Integer rest = house.getRest() + 1;
        house.setRest(rest);
        houseService.updateOne(house);

        removeById(id);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult updateOne(Reserve reserve) {
        UpdateWrapper<Reserve> updateWrapper = new UpdateWrapper();
        // TODO：
        return update(updateWrapper) ? ResponseResult.okResult() : ResponseResult.errorResult(AppHttpCodeEnum.UPDATE_ERROR);
    }

    @Override
    public ResponseResult getReserveByUserId(Integer userId) {
        LambdaQueryWrapper<Reserve> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Reserve::getUserId, userId)
                .eq(Reserve::getIsPay, SysConst.NO_PAY);
        List<Reserve> list = list(queryWrapper);
        List<ReserveVo> collect = list.stream().map((reserve -> {
            ReserveVo reserveVo = BeanCopyUtils.copyBean(reserve, ReserveVo.class);
            LambdaQueryWrapper<House> houseQueryWrapper = new LambdaQueryWrapper<>();
            houseQueryWrapper.eq(House::getId, reserve.getHouseId());
            House house = houseService.getOne(houseQueryWrapper);
            if (!Objects.isNull(house)) {
                reserveVo.setImg(house.getImg());
                reserveVo.setDes(house.getDes());
                reserveVo.setTitle(house.getTitle());
                reserveVo.setPrice(house.getPrice());
                reserveVo.setAddress(house.getAddress());
                long days = DateUtil.calculateDaysBetween(reserve.getStartTime(), reserve.getEndTime());
                reserveVo.setDays((int) days);
                reserveVo.setTotalPrice(days * reserveVo.getPrice());
                reserveVo.setAddress(house.getAddress());
            }
            return reserveVo;
        })).collect(Collectors.toList());

        return ResponseResult.okResult(collect);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult deleteBatchByIds(IdList ids) {
        ids.getIds().stream().forEach(reserveId -> {
            Reserve reserve = getById(reserveId);
            Long houseId = reserve.getHouseId();
            House house = houseService.getById(houseId);
            Integer rest = house.getRest() + 1;
            house.setRest(rest);
            houseService.updateOne(house);
        });
        removeByIds(ids.getIds());
        return ResponseResult.okResult();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult updateBatchByIds(IdList reserveList) {
        LambdaUpdateWrapper<Reserve> updateWrapper = new LambdaUpdateWrapper<>();
        List<Integer> ids = reserveList.getIds();
        updateWrapper.in(Reserve::getId, ids)
                .set(Reserve::getIsPay, 1);
        update(null, updateWrapper);

        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getNoPayReserveByUserId(Integer userId) {
        LambdaQueryWrapper<Reserve> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Reserve::getUserId, userId)
                .eq(Reserve::getIsPay, SysConst.IS_PAY);
        List<Reserve> list = list(queryWrapper);
        List<ReserveVo> collect = list.stream().map((reserve -> {
            ReserveVo reserveVo = BeanCopyUtils.copyBean(reserve, ReserveVo.class);
            LambdaQueryWrapper<House> houseQueryWrapper = new LambdaQueryWrapper<>();
            houseQueryWrapper.eq(House::getId, reserve.getHouseId());
            House house = houseService.getOne(houseQueryWrapper);
            if (!Objects.isNull(house)) {
                reserveVo.setImg(house.getImg());
                reserveVo.setTitle(house.getTitle());
                reserveVo.setDes(house.getDes());
                reserveVo.setPrice(house.getPrice());
                reserveVo.setAddress(house.getAddress());
                long days = DateUtil.calculateDaysBetween(reserve.getStartTime(), reserve.getEndTime());
                reserveVo.setDays((int) days);
                reserveVo.setTotalPrice(days * reserveVo.getPrice());
                reserveVo.setAddress(house.getAddress());
            }
            return reserveVo;
        })).collect(Collectors.toList());

        return ResponseResult.okResult(collect);
    }

    @Override
    public ResponseResult search(Integer pageNum, Integer pageSize, Integer isPay, Integer userId, Integer houseId) {
        LambdaQueryWrapper<Reserve> queryWrapper = new LambdaQueryWrapper<>();
        if (!Objects.isNull(userId)) {
            queryWrapper.eq(Reserve::getUserId, userId);
        }
        if (!Objects.isNull(houseId)) {
            queryWrapper.eq(Reserve::getHouseId, houseId);
        }
        if (!Objects.isNull(isPay)) {
            queryWrapper.eq(Reserve::getIsPay, isPay);
        }
        Page<Reserve> reservePage = new Page<>(pageNum, pageSize);
        page(reservePage, queryWrapper);
        PageVo<Reserve> reservePageVo = new PageVo<>();
        reservePageVo.setTotal(reservePage.getTotal());
        reservePageVo.setPageTotal(reservePage.getPages());
        reservePageVo.setResult(reservePage.getRecords());

        return ResponseResult.okResult(reservePageVo);
    }

}

